/**
 * 用来批量替换从 plain-design-doc 中迁移过来的文档
 * @author  韦胜健
 * @date    2021/10/8 16:42
 */

const IterateUtils = require('./replace.doc.utils')

interface ReplaceConfig {
    entries: string | string[],
    exclude?: { files: RegExp, dirs: RegExp },
}

function replace({entries, exclude}: ReplaceConfig) {
    const paths = Array.isArray(entries) ? entries : [entries]
    paths.forEach(path => {
        IterateUtils.iterate({
            path,
            excludeDirectoryRegExp: exclude?.dirs,
            excludeFileRegexp: exclude?.files,
            handleFile: (fileRelativePath: string) => {
                const filePath = IterateUtils.resolve(fileRelativePath)
                const fileContent: string = IterateUtils.fs.readFileSync(filePath).toString('utf8')

                const kebabCase = (str: string): string => {
                    if (str.length > 1 && /[A-Z]/.test(str.charAt(0))) {
                        str = str.charAt(0).toLowerCase() + str.substring(1)
                    }
                    return str.replace(/[A-Z]/g, (i) => '-' + i.toLowerCase())
                }

                const newFileContent = fileContent!.replace(/:::case((?:.|\n|\r)*?):::/g, (...args) => {
                    let caseString = args[0]
                    /*
                    *  plain-design 替换为 plain-ui
                    *  import React移除
                    *  $$message 替换为 $message
                    *  className= 改为 class=
                    *  react node中的组件名称，从驼峰命名改为横岗命名
                    *  事件名称改为@+横岗命名
                    *  属性的单向绑定语法，从原本的大括号改为 冒号绑定
                    *  把```css```改为 <style>
                    */

                    // plain-design 替换为 plain-ui
                    caseString = caseString.replace(/plain-design/g, 'plain-ui')
                    // import React移除
                    caseString = caseString.replace(/import React from ['"]react['"];?/g, '')
                    // className= 改为 class=
                    caseString = caseString.replace(/className/g, 'class')
                    // $$message 替换为 $message
                    caseString = caseString.replace(/\$\$message/g, '$message')
                    // react node中的组件名称，从驼峰命名改为横岗命名
                    caseString = caseString.replace(/<\/?([A-Z][a-zA-Z]*)/g, (input, group1) => {
                        return input.replace(group1, kebabCase(group1))
                    })
                    // 事件名称改为@+横岗命名
                    caseString = caseString.replace(/on([A-Z][a-zA-Z]+)=\{(.+?)\}/g, (input, group1, group2) => {
                        return `@${kebabCase(group1)}="${group2}"`
                    })
                    // 属性的单向绑定语法，从原本的大括号改为 冒号绑定
                    caseString = caseString.replace(/\s*([a-zA-Z-]+)=\{(.+?)\}(\s|>|\/>)/g, (input, group1, group2) => {
                        return input.replace(group1, group1.indexOf('v-model') > -1 ? group1 : `:${group1}`)
                            .replace(`{${group2}}`, `"${group2.replace(/"/g, `'`)}"`)
                    })

                    const content: {
                        template?: string,
                        script?: string,
                        style?: string,
                    } = {}
                    // 把```css```改为 <style>
                    caseString = caseString.replace(/```css((?:.|\r|\n)*?)```/g, (input, group1) => {
                        content.style = `<style>${group1}</style>`
                        return ''
                    })
                    caseString = caseString.replace(/```jsx((?:.|\r|\n)*?)```/g, (input, group1) => {
                        let jsxCode = group1 as string
                        jsxCode = jsxCode.replace(/(?:return|export default) \(\)(?:.|\n|\r)*?(<[a-z](?:.|\r|\n)*)([^<]\/>|\/.+>)/g, (_, group1, group2) => {
                            content.template = group1 + group2
                            return 'return ???'
                        })
                        /*if (!content.template) {
                            console.log(jsxCode)
                        }*/
                        jsxCode = jsxCode.replace(/((?:.|\n|\r)*)export default/, (input, group1) => {
                            content.script = (content.script || '') + group1
                            return 'export default'
                        })
                        if (jsxCode.indexOf('export default designPage') > -1) {
                            jsxCode.replace(/export default designPage.*((?:.|\n|\r)*?)return \?\?\?/, (_, group1) => {
                                content.script = (content.script || '') + `export default {\nsetup(){\n${group1}\n}\n}`
                                return ''
                            })
                        }
                        return "```vue\n" + [
                            !!content.template ? `<template>\n${content.template}\n</template>` : null,
                            !!content.script ? `<script>${content.script}</script>` : null,
                            !!content.style ? content.style : null,
                        ].filter(Boolean).join('\n') + "\n```"
                    })
                    return caseString
                })
                IterateUtils.fs.writeFileSync(filePath, newFileContent)
            }
            ,
        })
    })
}

replace({
    entries: [
        // 'src/doc/components/',
        // 'src/doc/components/grid.md'
        // 'src/doc/components/view/tree.md'
        // 'src/doc/components/input.md',
        // 'src/doc/components/radio.md',
        // 'src/doc/components/checkbox.md',
        // 'src/doc/components/number.md',
        // 'src/doc/components/loading.md',
        // 'src/doc/components/select.md',
        // 'src/doc/components/toggle.md',
        // 'src/doc/components/slider.md',
        // 'src/doc/components/tag.md',
        // 'src/doc/components/rate.md',
        // 'src/doc/components/color-picker.md',
        // 'src/doc/components/cascade.md',
        // 'src/doc/components/time.md',
        // 'src/doc/components/date.md',
        // 'src/doc/components/upload.md',
        // 'src/doc/components/image.md',
        // 'src/doc/components/form',
        // 'src/doc/components/view/list.md',
        // 'src/doc/components/view/virtual-list.md',
        // 'src/doc/components/view/progress.md',
        // 'src/doc/components/view/tree.md',
        // 'src/doc/components/view/pagination.md',
        // 'src/doc/components/view/badge.md',
        // 'src/doc/components/view/step.md',
        // 'src/doc/components/view/tab.md',
        // 'src/doc/components/other/scroll.md',
        // 'src/doc/components/other/dialog.md',
        // 'src/doc/components/other/tooltip.md',
        // 'src/doc/components/other/dropdown.md',
        // 'src/doc/components/other/popper.md',
        // 'src/doc/components/other/card.md',
        // 'src/doc/components/other/carousel.md',
        // 'src/doc/components/other/collapse.md',
        // 'src/doc/components/other/alert.md',
        // 'src/doc/components/service/$message.md',
        // 'src/doc/components/service/$notice.md',
        // 'src/doc/components/service/$dialog.md',
        // 'src/doc/components/service/$file.md',
        // 'src/doc/components/table',
        'src/doc/components/plain-table',
    ],
})
